#pragma once

#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include <sys/epoll.h>
#include <functional>
#include "Epoller.hpp"
#include "comm.hpp"
#include "Socket.hpp"
#include "log.hpp"

// 声明
class Connection;
class TcpServer;

uint32_t EVENT_IN = (EPOLLIN | EPOLLET);
uint32_t EVENT_OUT = (EPOLLOUT | EPOLLET);

using func_t = std::function<void(std::weak_ptr<Connection>)>;
using excpet_func = std::function<void(std::weak_ptr<Connection>)>;

class Connection
{
public:
    Connection(int sock)
        : _sock(sock)
    {
    }

    void SetHandler(func_t recv_cb,func_t send_cb,excpet_func except_cb)
    {
        _recv_cb = recv_cb;
        _send_cb = send_cb;
        _except_cb = except_cb;
    }

    void SetWeakptr(std::weak_ptr<TcpServer> tcp_server_ptr)
    {
        _tcp_server_ptr = tcp_server_ptr;
    }

    ~Connection()
    {
    }

private:
    int _sock;

public:
    func_t _recv_cb;
    func_t _send_cb;
    excpet_func _except_cb;

    std::string _ip;
    uint16_t _port;
    std::weak_ptr<TcpServer> _tcp_server_ptr;

};

class TcpServer :public std::enable_shared_from_this<TcpServer>, public nocopy
{
    static const int num = 64;

public:

    TcpServer(uint16_t port)
    :_port(port),
    _epoller_ptr(new Epoller()),
    _listensock_ptr(new Sock()),
    _qiut(true)
    {}

    void Init()
    {
        _listensock_ptr->Socket();
        Setnonblock(_listensock_ptr->Fd());
        _listensock_ptr->Bind(_port);
        _listensock_ptr->Listen();
        lg(INFO, "create listen socket success: %d", _listensock_ptr->Fd());
        AddConnection(_listensock_ptr->Fd(),EVENT_IN,
            bind(&TcpServer::Accpeter,this,std::placeholders::_1),nullptr,nullptr);
        
    }

    void Accpeter()
    {

    }
    
    void AddConnection(int sock ,uint32_t event,func_t recv_cb,func_t send_cb,
            excpet_func except_cb,const std::string& ip, uint16_t port)
    {
        std::shared_ptr<Connection> new_connection(new Connection(sock));
        new_connection->SetWeakptr(shared_from_this()); //继承类，获取share_ptr
        new_connection->SetHandler(recv_cb,send_cb,except_cb);
        new_connection->_ip = ip;
        new_connection->_port = port;
        
        //用户维护的空间
        _connections.insert({sock,new_connection});
        
        _epoller_ptr->EpollUpdate(EPOLL_CTL_DEL,sock,event);

    }

    void Loop()
    {

    }

    ~TcpServer()
    {}

private:
    std::shared_ptr<Epoller> _epoller_ptr;
    std::shared_ptr<Sock> _listensock_ptr;
    std::unordered_map<int, std::shared_ptr<Connection>> _connections;
    struct epoll_event revs[num];
    uint16_t _port;
    bool _qiut;
};